import UIKit

var str = "Hello, playground"

//在Swift语言中，所有的错误和异常都由Error协议来指定。例如，开发者可以编写自定义的枚举类型，使其遵守Error协议来描述所需求的异常类型


//自定义的异常类型
enum MyError:Error {
    //定义3种程度的异常
    case DesTroyError
    case NormalError
    case SimpleError
}

print("should error")
//进行异常的抛出
//throw MyError.DesTroyError
print("finish")

//上面的示例代码自定义了一种异常类型，之后在代码中通过throw关键字进行了异常的抛出。需要注意，抛出的异常如果不进行捕获解决，程序会断在抛出异常的地方，如上所示将不会打印“finish”。


//函数在执行时，也可能会产生异常，默认情况下，函数中产生的异常只能在函数内部解决，开发者也可以使用throws关键字将此函数声明为可抛异常函数，如此声明则允许开发者在函数外解决函数内部抛出的异常，创建一个可抛出异常的函数示例代码如下：
func myFunc(param:Bool) throws -> Bool{
    if param {
        print("success")
    }else{
        print("出错了")
        throw MyError.NormalError
    }
    return param
}


//首先do-catch结构是Swift语言中处理异常的最常用方法，开发者需要将可能抛出异常的代码放入do结构块中，如果这部分代码中有抛出异常，则会从catch块中寻找对应的异常类型，如果找到对应的，就会执行此catch块中的异常处理代码
do {
    try myFunc(param: false)
}catch MyError.SimpleError{
    print("SimpleError")
}catch MyError.NormalError{
    print("NormalError")
}catch MyError.DesTroyError{
    print("DesTroyError")
}catch{
    print("otherError")
}


//有些时候开发者可能并不关心产生异常的类型与原因，只需要知道有没有产生异常，对于这种情况，使用do-catch结构会显得十分烦琐冗余。Swift语言还提供了另一种方法，可以将异常映射为Optional值，如果函数正常运行，没有抛出异常，则正常返回。如果函数执行出错，抛出了异常，则会返回Optional值nil。使用try?来调用函数可以将异常映射为Optional值
var tmp = try? myFunc(param: false)
if tmp == nil{
    print("执行失败")
}else{
    print("执行成功")
}

//除了上述两种处理异常的场景外，还有一种比较极端的情况：当开发者可以保证此函数一定不会抛出异常时，便可以使用try!来强行终止异常的传递，然而这么做有一定的风险，如果这个函数真的抛出了异常，就会产生运行时错误
try! myFunc(param: true)
try! myFunc(param: false)
